/**
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import { UseUtil, NumberFormatter } from './types';
import { NumberRangeProps } from '../number-range.props';
import { SetupContext, Ref } from 'vue';
import { BigNumber } from 'bignumber.js';

export function UseUtil(
    props: NumberRangeProps,
    context: SetupContext,
    realValue: Ref<number | string | null>,
    formatOptions: Ref,
    targetValue: Ref<string>,
    beginValue: Ref<number | string | null>,
    endValue: Ref<number | string | null>
): UseUtil {
    /**
     * 判断输入框中的值是否为空
     * @param val 输入值
     * @returns 返回是否时空值的判断结果
     */
    function isEmpty(val: any): boolean {
        return isNaN(val) || val === null || val === undefined || val === '';
    }
    /**
     * 设置输入框是否为可用状态
     * @param isDisabled 要设置的输入框状态
     */
    function setDisabledState(isDisabled: boolean): void {
        props.disabled = isDisabled;
    }

    /**
     * 清洗数据为数字
     * @param val 输入值，带有前缀、后缀等
     * @returns 返回的纯数字数据
     */
    function cleanNumString(val: any) {
        val = val === null || val === undefined || val === '' ? '' : String(val);
        val = val.replace(new RegExp(props.prefix, 'g'), '').replace(new RegExp(props.suffix, 'g'), '').replace(/\,/g, '');
        if (props.groupSeparator && props.groupSeparator !== ',') {
            val = val.replace(new RegExp(`\\${props.groupSeparator}`, 'g'), '');
        }

        if (props.decimalSeparator && props.decimalSeparator !== '.') {
            val = val.replace(new RegExp(`\\${props.decimalSeparator}`, 'g'), '.');
        }
        return val;
    }

    /**
     * 获取精度
     * @returns 返回精度具体值
     */
    function getPrecision() {
        return Number(props.precision || 0);
    }

    /**
     * 基于精度参数修改tofixed方法
     * @param value
     * @returns
     */
    function toFixed(value: BigNumber | number) {
        if (props.precision !== null && props.precision !== undefined) {
            return value.toFixed(getPrecision());
        }
        return value.toFixed();
        5;
    }

    /**
     * 获取实际数值,支持大数时返回bigNumber类型，否则返回Number类型
     * @param value
     * @returns
     */
    function _getRealValue(value: BigNumber) {
        const fixedValue = toFixed(value);
        return props.bigNumber ? fixedValue : Number(value);
    }
    /**
     * 输入框真实数值修改，并通知回调
     * @param realVal
     * @param target 微调时未聚焦，taregtValue值不存在，使用target辅助定位按钮
     */
    function _modelChanged(realVal: any, target?: string) {
        if (!target) {
            target = targetValue.value;
        }

        if (target === 'beginValue') {
            beginValue.value = realVal;
            context.emit('beginValueChange', realVal);
        } else if (target === 'endValue') {
            endValue.value = realVal;
            context.emit('endValueChange', realVal);
        }
        // realValue.value = realVal;
    }
    /**
     * 最值校验
     * @param bn
     * @returns
     */
    function validInterval(bn: BigNumber, target?: string) {
        let _bnVal = bn;

        if (!isEmpty(props.max)) {
            const _maxBigNum = new BigNumber('' + props.max);
            if (bn.gt(_maxBigNum)) {
                _bnVal = _maxBigNum;
                const _resultValue = _getRealValue(_maxBigNum);
                _modelChanged(_resultValue, target);
            }
        }

        if (!isEmpty(props.min)) {
            const _minBigNum = new BigNumber('' + props.min);
            if (bn.lt(_minBigNum)) {
                _bnVal = _minBigNum;
                const _resultValue = _getRealValue(_minBigNum);
                _modelChanged(_resultValue, target);
            }
        }

        return _bnVal;
    }
    /**
     * 获取实际数值
     * @param val
     * @returns
     */
    function getRealValue(val: any, target?: string) {
        if (props.parser) {
            if (!isNaN(Number(val))) {
                return val;
            }
            return props.parser(val);
        }

        let value = validInterval(new BigNumber(val), target);
        if (value.isNaN()) {
            if (props.canNull) {
                return null;
            }
            const minBigNum = new BigNumber('' + props.min);
            const maxBigNum = new BigNumber('' + props.max);

            if (!minBigNum.isNaN()) {
                value = minBigNum;
            } else if (!maxBigNum.isNaN()) {
                value = maxBigNum;
            } else {
                return 0;
            }

            // if (this.canNull || minBigNum.isNaN()) {
            //     return null;
            // } else {
            //     value = minBigNum;
            // }
        }

        return _getRealValue(value);
    }

    /**
     * 判断为按钮是否为可用
     * @param type 'up'|'down'
     * @param value 输入框的真实数字值
     * @returns true为可用， false不可用
     */
    function isDisableOfBtn(type: string, value?: any) {
        if (value === undefined) {
            value = realValue.value;
        }
        value = new BigNumber(value);

        if (type === 'up' && props.max && !new BigNumber(props.max).isNaN() && value.gte(new BigNumber(props.max))) {
            return false;
        }
        if (type === 'down' && props.min && !new BigNumber(props.min).isNaN() && value.lte(new BigNumber(props.min))) {
            return false;
        }
        return true;
    }

    /**
     * 生成格式化对象
     */
    function buildFormatOptions() {
        return {
            prefix: props.prefix,
            suffix: props.suffix,
            decimalSeparator: props.decimalSeparator,
            groupSeparator: props.useThousands ? props.groupSeparator : '',
            groupSize: props.groupSize
        };
    }

    function _toFormat(_bgNum: BigNumber, fmt: NumberFormatter) {
        if (props.precision !== null && props.precision !== undefined) {
            return _bgNum.toFormat(getPrecision(), fmt);
        }
        return _bgNum.toFormat(fmt);
    }

    /**
     * 格式化数据
     * */
    function format(val: any) {
        val = cleanNumString(val);
        const bigVal = new BigNumber(val);
        const _bgNum = validInterval(bigVal);

        if (_bgNum.valueOf() === '0' && !props.showZero) {
            return '';
        }

        if (props.canNull && bigVal.isNaN()) {
            return '';
        }
        if (_bgNum.isNaN()) {
            return '';
        }

        if (props.formatter) {
            return props.formatter(_bgNum.toNumber());
        }
        if (!Object.keys(formatOptions.value).length) {
            formatOptions.value = buildFormatOptions();
        }

        return _toFormat(_bgNum, formatOptions.value);
    }

    return {
        isEmpty,
        setDisabledState,
        cleanNumString,
        getPrecision,
        toFixed,
        _getRealValue,
        getRealValue,
        isDisableOfBtn,
        buildFormatOptions,
        _modelChanged,
        validInterval,
        format,
        _toFormat
    };
}
